package com.heima.article.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.heima.article.service.IApArticleFreemarkerService;
import com.heima.article.service.IApArticleService;
import com.heima.common.constants.ArticleConstants;
import com.heima.miniofile.service.MinIoFileStorageService;
import com.heima.model.article.pojos.ApArticle;
import com.heima.model.search.vos.SearchArticleVo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.HashMap;


@Service
@Slf4j
@Transactional
public class ApArticleFreemarkerServiceImpl implements IApArticleFreemarkerService {
    @Autowired
    private KafkaTemplate<String, String> kafkaTemplate;
    @Autowired
    @Lazy
    private IApArticleService apArticleService;
    @Autowired
    private MinIoFileStorageService file;
    @Autowired
    private Configuration configuration;

    /**
     * 生成静态文件上传到 MinIo
     *
     * @param apArticle 文章信息
     * @param content   文章内容
     */
    @Override
    @Async // 开启异步任务
    public void buildArticleToMinIo(ApArticle apArticle, String content) {

        // 1. 通过文章内容生成html文件
        Template template = null;
        try {
            template = configuration.getTemplate("article.ftl");
        } catch (IOException e) {
            log.warn("上传文章: 获取模板文件失败");
            throw new RuntimeException(e);
        }
        // 数据模型
        HashMap<String, Object> contentDataModel = new HashMap<>();
        contentDataModel.put("content", JSONArray.parseArray(content));
        StringWriter out = new StringWriter();

        try {
            template.process(contentDataModel, out);
        } catch (TemplateException | IOException e) {
            log.warn("上传文章: 生成html文件失败");
            throw new RuntimeException(e);
        }

        // 2. 将html文件上传到minio
        InputStream in = new ByteArrayInputStream(out.toString().getBytes());
        String path = file.uploadHtmlFile("article", apArticle.getId() + ".html", in);

        // 3. 插入文章表, 更新static_url字段
        System.out.println(apArticleService.lambdaUpdate()
                .eq(ApArticle::getId, apArticle.getId())
                .set(ApArticle::getStaticUrl, path).update());

        // 发送消息，创建索引
        createArticleESIndex(apArticle, content, path);

    }

    /**
     * 送消息，创建索引
     *
     * @param apArticle  文章对象
     * @param content   文章内容
     * @param path  静态资源 url
     */
    private void createArticleESIndex(ApArticle apArticle, String content, String path) {
        SearchArticleVo vo = new SearchArticleVo();
        BeanUtils.copyProperties(apArticle, vo);
        vo.setContent(content);
        vo.setStaticUrl(path);

        kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(vo));
    }

}
